/**
 * 
 */
package com.lorizz.picpub.services.impl;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Random;
import java.util.UUID;

import javax.imageio.ImageIO;

import org.apache.commons.io.FileUtils;

import com.lorizz.picpub.services.ImageStore;
import com.sun.image.codec.jpeg.ImageFormatException;
import com.sun.image.codec.jpeg.JPEGCodec;

/**
 * @author wind hong
 * 
 */
public class ImageStoreImpl implements ImageStore {

    private static final String SCHEME = "store://";
    private String localPath;
    private String externalUrlPrefix;
    private String[] dirs;
    private Random random = new Random();
    private int pathLevel;
    
	public ImageStoreImpl() {
		dirs = new String[26];
		for (int i = 0; i < 26; i++) {
			dirs[i] = Character.toString((char)('a' + i));
		}
	}
	
	public void setPathLevel(int pathLevel) {
		this.pathLevel = pathLevel;
	}

    public void setLocalPath(String localPath) {
        this.localPath = localPath;
        if (!this.localPath.endsWith("/"))
            this.localPath += "/";
    }

    public void setExternalUrlPrefix(String externalUrlPrefix) {
        this.externalUrlPrefix = externalUrlPrefix;
    }

    public void init() {
        File file = new File(localPath);
        if (!file.exists() && !file.mkdirs())
            throw new RuntimeException("Can not find directory [" + localPath + "]");
    }

    @Override
    public BufferedImage load(String uri) {
        try {
            File file = new File(uri.replace(SCHEME, localPath));
            return ImageIO.read(file);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public String store(String category, BufferedImage image) {
        String uuid = UUID.randomUUID().toString();
        try {
        	String path = getStorePath(category);
        	createPath(path);
            FileOutputStream out = new FileOutputStream(localPath + path + uuid + ".jpg");
            JPEGCodec.createJPEGEncoder(out).encode(image);
            out.close();
            return SCHEME + path + uuid + ".jpg";
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (ImageFormatException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

	@Override
    public String store(String category, File image) {
        String fileName = image.getName();
        String ext = "";
        int idx = fileName.lastIndexOf(".");
        if (idx != -1)
            ext = fileName.substring(idx + 1);
        String uuid = UUID.randomUUID().toString();
        String newFileName = uuid + (ext.isEmpty() ? "" : ("." + ext));
        String path = getStorePath(category);
        createPath(path);
        File newFile = new File(localPath + path + newFileName);
        try {
            FileUtils.copyFile(image, newFile);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return SCHEME + path + newFileName;
    }
	
	private void createPath(String path) {
		File file = new File(localPath + path);
		if (!file.exists()) {
			file.mkdirs();
		}
	}
    
    private String getStorePath(String category) {
		StringBuilder path = new StringBuilder();
		if (category != null && category.length() > 0)
			path.append(category).append("/");
		for (int i = 0; i < pathLevel; i++) {
			path.append(dirs[random.nextInt(dirs.length)]).append("/");
		}
		return path.toString();
    }

    @Override
    public String toExternalURL(String internalUri) {
        return internalUri.replaceFirst(SCHEME, externalUrlPrefix);
    }

}
